/**
 * Copyright (c) 2016-2019 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有，侵权必究！
 */

package com.gill.jwt.util;

import com.gill.jwt.config.properties.JwtProperties;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Map;

/**
 * jwt工具类
 *
 * @author Mark sunlightcs@gmail.com
 */
@Slf4j
public class JwtUtil {

    private static volatile JwtUtil jwtUtil;

    private JwtProperties jwtProperties;

    private JwtUtil(){

    }

    public static JwtUtil getInstance(JwtProperties jwtProperties){
        if(jwtProperties == null){
            throw new RuntimeException("jwtProperties can't not be null");
        }
        if(jwtUtil == null){
            synchronized (JwtUtil.class){
                if(jwtUtil == null){
                    jwtUtil = new JwtUtil();
                    jwtUtil.jwtProperties = jwtProperties;
                }
            }
        }
        return jwtUtil;
    }

    /**
     * 根据用户信息生成token
     *
     * @param claims 用户信息
     * @return token
     */
    public String generateToken(Map<String, Object> claims) {
        Date createdTime = new Date();
        Date expirationTime = new Date(System.currentTimeMillis() + jwtProperties.getExpire() * 1000);


        byte[] keyBytes = jwtProperties.getSecret().getBytes();
        SecretKey key = Keys.hmacShaKeyFor(keyBytes);

        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(createdTime)
                .setExpiration(expirationTime)
                // 你也可以改用你喜欢的算法
                // 支持的算法详见：https://github.com/jwtk/jjwt#features
                .signWith(key, SignatureAlgorithm.HS256)
                .compact();
    }

    /**
     * 判断token是否有效
     *
     * @param token token
     * @return 未过期返回true，否则返回false
     */
    public Boolean isTokenValid(String token) {
        Date expiration = getClaimsFromToken(token).getExpiration();
        return expiration.after(new Date());
    }


    /**
     * 从token中获取claim
     *
     * @param token token
     * @return claim
     */
    public Claims getClaimsFromToken(String token) {
        try {
            return Jwts.parser()
                    .setSigningKey(jwtProperties.getSecret().getBytes())
                    .parseClaimsJws(token)
                    .getBody();
        } catch (ExpiredJwtException | UnsupportedJwtException | MalformedJwtException | IllegalArgumentException e) {
            throw new IllegalArgumentException("Token invalided.");
        }
    }

}
